package com.bw.zzy.partal2.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.bw.zzy.partal2.common.OperationMessage;
import com.bw.zzy.partal2.db.dao.DoctorWorkPlanDao;
import com.bw.zzy.partal2.exception.GlobalException;
import com.bw.zzy.partal2.pojo.DoctorWorkPlan;
import com.bw.zzy.partal2.pojo.DoctorWorkPlanSchedule;
import com.bw.zzy.partal2.service.DoctorWorkPlanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Slf4j
public class DoctorWorkPlanServiceImpl implements DoctorWorkPlanService {

    @Autowired
    private DoctorWorkPlanDao doctorWorkPlanDao;


    @Autowired
    private DoctorWorkPlanScheduleServiceImpl doctorWorkPlanScheduleService;


    @Override
    public JSONArray selectWorkPlanByTime(Map param, ArrayList dateList) {
        ArrayList<HashMap> list = doctorWorkPlanDao.selectWorkPlanByTime(param);
        Integer tempSubId = null;
        String tempDate = null;
        HashMap tempResult = new HashMap();
        for (HashMap one : list) {
            String deptName = MapUtil.getStr(one, "deptName");
            int deptSubId = MapUtil.getInt(one, "deptSubId");
            String deptSubName = MapUtil.getStr(one, "deptSubName");
            String doctorName = MapUtil.getStr(one, "doctorName");

            String date = MapUtil.getStr(one, "date");


            //判断是不是某个诊室第一条记录
            if (tempSubId == null) {
                tempSubId = deptSubId;
                tempDate = date;

                //把第一条记录当作一个诊室
                HashMap temp = new HashMap() {{
                    put("dateName", deptName);
                    put("deptSubId", deptSubId);
                    put("deptSubName", deptSubName);

                    put("plan", new LinkedHashMap<>() {{
                        put(date, new ArrayList<>() {{
                            add(doctorName);
                        }});
                    }});
                }};
                tempResult.put(deptSubId, temp);
            } else if (tempSubId == deptSubId && tempDate.equals(date)) {
                HashMap map = (HashMap) tempResult.get(deptSubId);

                LinkedHashMap plan = (LinkedHashMap) map.get("plan");

                ArrayList doctors = (ArrayList) plan.get(date);

                doctors.add(doctorName);
            } else if (tempSubId == deptSubId && !tempDate.equals(date)) {
                tempDate = date;

                HashMap map = (HashMap) tempResult.get(deptSubId);

                LinkedHashMap plan = (LinkedHashMap) map.get("plan");

                plan.put(date, new ArrayList<>() {{
                    add(doctorName);
                }});
            } else if (tempSubId != deptSubId) {
                tempSubId = deptSubId;
                tempDate = date;

                HashMap temp = new HashMap() {{
                    put("deptName", deptName);
                    put("deptSubId", deptSubId);
                    put("deptSubName", deptSubName);

                    put("plan", new LinkedHashMap<>() {{
                        put(date, new ArrayList<>() {{
                            add(doctorName);
                        }});
                    }});
                }};
                tempResult.put(deptSubId, temp);
            }
        }


        Set<Map.Entry> set = tempResult.entrySet();

        set.forEach(one->{

            HashMap map = (HashMap) one.getValue();

            LinkedHashMap plan = (LinkedHashMap) map.get("plan");

            dateList.forEach(date->{
                if (!plan.containsKey(date)){
                    plan.put(date, new ArrayList<>());
                }
            });

            TreeMap sort = MapUtil.sort(plan, new Comparator() {

                @Override
                public int compare(Object o1, Object o2) {
                    String key1 = (String) o1;
                    String key2 = (String) o2;
                    boolean bool = new DateTime(key1).isAfter(new DateTime(key2));
                    return bool ? 1 : -1;
                }
            });
            map.replace("plan", sort);
        });

        Collection<HashMap> values = tempResult.values();
        values.forEach(one->{
            TreeMap plan = (TreeMap) one.get("plan");

            Set<Map.Entry> tempSet = plan.entrySet();
            ArrayList temp = new ArrayList();

            tempSet.forEach(entry -> {
                temp.add(new HashMap<>() {{
                    put("date", entry.getKey());
                    put("doctors", entry.getValue());
                }});
            });
            one.replace("plan", temp);
        });
        return JSONUtil.parseArray(values);
    }



    @Override
    public String insert(Map param) {
        Integer id = doctorWorkPlanDao.selectIdByDoctorAndSubId(param);

        //如果已经存在出诊计划，就不让添加了
        if (id != null) {
            // 直接返回一个枚举类型的字符串
           return  OperationMessage.PLAN_EXISTS.toString();
        }

        //绑定提交的参数到 DoctorWorkPlan 实例
        DoctorWorkPlan doctorWorkPlan = BeanUtil.toBean(param, DoctorWorkPlan.class);
        //DoctorWorkPlan 中的 maximum 和 参数传来的 totalMaximum 映射不了，要取出参数，手动赋值
        doctorWorkPlan.setMaximum(Integer.parseInt(param.get("totalMaximum").toString()));

        // 这是 插入数据时 num 为null 导致有问题 自己做的
        if (doctorWorkPlan.getNum() == null) {
            doctorWorkPlan.setNum(0);
        }

        //保存出诊计划
        doctorWorkPlanDao.insert(doctorWorkPlan);

        //查询work_plan_id
        id = doctorWorkPlanDao.selectIdByDoctorAndSubId(param);
        /*
        * 例如选择的是
        *           08:00 - 08:30
        *           08:30 - 09:30
        *           16:30 - 17:30
        *
        * 那么数字中存储的是：[1,2,15]
        * */
        Integer[] slots = (Integer[]) param.get("slots");
        //从参数中取出选择时段的人数    就是每个时间段要看多少个人
        int slotMaximum = Integer.parseInt(param.get("slotMaximum").toString());
        ArrayList<DoctorWorkPlanSchedule> list = new ArrayList<>();
        for (Integer slot : slots) {
            /*
            *   循环时间段生成医生出诊记录
            * */
            DoctorWorkPlanSchedule doctorWorkPlanSchedule = BeanUtil.toBean(param, DoctorWorkPlanSchedule.class);
            //设置门诊日程表的id
            doctorWorkPlanSchedule.setWorkPlanId(id);
            //设置具体的时段
            doctorWorkPlanSchedule.setSlot(slot);
            //设置时段人数
            doctorWorkPlanSchedule.setMaximum(slotMaximum);

            list.add(doctorWorkPlanSchedule);
        }
        // 保存数据库的关系表
        doctorWorkPlanScheduleService.insert(list);

        return OperationMessage.PLAN_SAVE_OK.toString();
    }

    @Override
    @Transactional
    public void deleteWorkPlan(Integer workPlanId) {
        Integer num = doctorWorkPlanDao.selectNumById(workPlanId);

        if (num > 0) {
            throw new GlobalException("该出诊计划已经有患者挂号，禁止删除");
        }

        // 首先删除出诊计划对应的时段
        doctorWorkPlanScheduleService.deleteByWorkPlanId(workPlanId);
        //删除出诊计划

        doctorWorkPlanDao.deleteById(workPlanId);
    }
}
